/**
*
* Copyright (c) 2011~2012 galaxy engine team.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*
*  Abstract:
*    
*
*  Author:
*    freecnjet (freecnjet@gmail.com)
*
*  Revision History:
*    Created on: 2012-03-18
*
*/

#ifndef _REFLECT_SYSTEM_IMP_H_
#define _REFLECT_SYSTEM_IMP_H_

#include "Reflection.h"


__BEGIN_NAMESPACE


struct TypeImp {
	const char*   m_Name;
	int           m_Category;
	unsigned int  m_Length;

	TypeImp( const char* name, int category, size_t length )
		:m_Name(name), m_Category(category), m_Length(length)
	{}
};

struct ValueType : public TypeImp, public Type {
	ValueType(const char* name, int category, size_t length)
		: TypeImp(name, category, length)
	{}

	virtual const char* Name();
	virtual int Category();
	virtual unsigned int Length();
};

struct ReferenceTypeImp : public TypeImp, public ReferenceType {
    Type*         m_RefType;

	ReferenceTypeImp( Type* reftype )
		:TypeImp("", Type::TREFERENCE, 0), m_RefType(reftype)
	{}

	virtual const char* Name();
	virtual int Category();
	virtual unsigned int Length();
	virtual Type* ReferenceTo();
};


struct PointerTypeImp : public TypeImp, public PointerType {
	Type*         m_PtrType;

	PointerTypeImp( Type* ptrtype )
		:TypeImp("", Type::TPOINTER, sizeof(void*)), m_PtrType(m_PtrType)
	{}

	virtual const char* Name();
	virtual int Category();
	virtual unsigned int Length();
	virtual Type* PointerTo();
};


/**
 * enum
 */
struct EnumItem {
	const char* m_Name;
	int         m_Value;
};

struct EnumInfoImp : public EnumInfo {
	EnumItem* m_ItemPtr;

	EnumInfoImp() {}
	~EnumInfoImp() {}
	void BindItem(EnumItem* item) { m_ItemPtr=item; }
	virtual const char* Name();
	virtual int Value();
};

struct EnumTypeImp : public TypeImp, public EnumType {
	unsigned int m_ItemCount;
	EnumItem*    m_Items;

	EnumTypeImp(const char* name, size_t length, unsigned int count, EnumItem* items)
		:TypeImp(name, Type::TENUMERATION, length ), m_ItemCount(count), m_Items(items)
	{}

	virtual const char* Name();
	virtual int Category();
	virtual unsigned int Length();
	virtual unsigned int Count();
	virtual EnumInfo* Items(unsigned int iid);
};

/**
 * Class & Interface
 */
#define FLAG_ACCESS_PUBLIC    1
#define FLAG_ACCESS_PROTECTED 2
#define FLAG_ACCESS_PRIVATE   3
#define INVALID_OFFSET        0x0FFFFFFF

struct ParameterItem {
	Type*       m_Type;
	bool        m_IsOptional;
	const char* m_Name;
	void*       m_RawValue;
	const char* m_RawDefaultValue;
};

struct ParameterInfoImp : public ParameterInfo {
	ParameterItem* m_ItemPtr;

	ParameterInfoImp() {}
	~ParameterInfoImp() {}
	void BindItem(ParameterItem* item) { m_ItemPtr=item; }

	virtual Type* ParameterType();
	virtual bool IsOptional();
	virtual const char* Name();
	virtual void* RawDefaultValue();
}; 

struct MethodItem {
	unsigned int   m_Count;
	ParameterItem* m_Items;
	unsigned short m_Flags;
	Type*          m_ReturnType;
};

#define METHOD_FLAG_ACCESS_MASK 0x0003
#define METHOD_FLAG_STATIC_MASK 0x0004
#define METHOD_FLAG_VIRTUAL_MASK 0x0008
#define METHOD_FLAG_CONSTRUCTOR_MASK 0x0010

struct MethodInfoImp : public MethodInfo, public ParameterStack {
    MethodItem*    m_ItemPtr;
	unsigned int   m_Pid; //For push item

	MethodInfoImp(MethodItem* item):m_ItemPtr(item), m_Pid(0) {}
	~MethodInfoImp() {}

	// ParamterStack interface
	virtual unsigned int Count();
	virtual Type* GetParameterType(unsigned int pid);
	virtual void* GetRawParameter(unsigned int pid);
	virtual void Push(void* raw_value);

	// MethodInfo interface
	virtual bool IsPublic();
	virtual bool IsProtected();
	virtual bool IsPrivate();
	virtual bool IsStatic();
	virtual bool IsConstructor();
	virtual bool IsVirtual();
	virtual Type* ReturnType();
	virtual unsigned int ParameterCount();
	virtual ParameterInfo* Parameters(unsigned int pid);
	virtual ParameterStack* GetParameterStack();
	virtual int Invoke(void* obj ) = 0; // need implement this function for member methods
};

struct InterfaceTypeImpBase : public TypeImp {
	unsigned int    m_BaseCount;
	InterfaceType** m_BaseItems;
	unsigned int    m_MethodCount;
	MethodInfo*     m_Methods;

	InterfaceTypeImpBase(const char* name, unsigned int base_count, InterfaceType** bases,
		unsigned int method_count, MethodInfo* methods )
		:TypeImp(name, Type::TINTERFACE, sizeof(void*) ), m_BaseCount(base_count), m_BaseItems(bases),
		m_MethodCount(method_count), m_Methods(methods)
	{}

	InterfaceTypeImpBase(const char* name, int category, unsigned int len, unsigned int base_count, InterfaceType** bases,
		unsigned int method_count, MethodInfo* methods )
		:TypeImp(name, category, len ), m_BaseCount(base_count), m_BaseItems(bases),
		m_MethodCount(method_count), m_Methods(methods)
	{}
};

struct InterfaceTypeImp : public InterfaceTypeImpBase, public InterfaceType {
	InterfaceTypeImp(const char* name, unsigned int base_count, InterfaceType** bases,
		unsigned int method_count, MethodInfo* methods )
		:InterfaceTypeImpBase(name, base_count, bases, method_count, methods)
	{}

	InterfaceTypeImp(const char* name, int category, unsigned int len, unsigned int base_count, InterfaceType** bases,
		unsigned int method_count, MethodInfo* methods )
		:InterfaceTypeImpBase(name, category, len, base_count, bases, method_count, methods)
	{}

	virtual const char* Name();
	virtual int Category();
	virtual unsigned int Length();

	virtual unsigned int BaseCount();
	virtual InterfaceType* Bases(unsigned int bid);
	virtual unsigned int MethodCount();
	virtual MethodInfo* Methods(unsigned int mid);
};


#define FIELD_FLAG_ACCESS_MASK 0x0003
#define FIELD_FLAG_STATIC_MASK 0x0004
#define FIELD_FLAG_READ_MASK   0x0008
#define FIELD_FLAG_WRITE_MASK  0x0010

struct FieldItem {
	unsigned int m_Flags;
    Type*        m_Type;
	const char*  m_Name;
	void*        m_RawDefaultValue;
	unsigned int m_Offset;
};

struct FieldInfoImp : public FieldInfo {
	FieldItem* m_ItemPtr;

	FieldInfoImp() {}
	~FieldInfoImp() {}
	void BindItem(FieldItem* item) { m_ItemPtr = item; }

	virtual bool IsPublic();
	virtual bool IsProtected();
	virtual bool IsPrivate();
	virtual bool IsStatic();
	virtual bool CanRead();
	virtual bool CanWrite();
	virtual Type* FieldType();
	virtual const char* Name();
	virtual void* RawDefaultValue();
	virtual void SetValue(void* obj, void* val );
	virtual void* GetValue(void* obj);
};

struct ClassTypeImp : public InterfaceTypeImpBase, public ClassType {

	unsigned int m_FieldCount;
	FieldInfo*   m_Fields;
	
	ClassTypeImp(const char* name, unsigned int base_count, InterfaceType** bases, size_t length, unsigned int method_count, MethodInfo* methods,
		unsigned int field_count, FieldInfo* fields	)
		:InterfaceTypeImpBase(name, Type::TCLASS, length, base_count, bases, method_count, methods), m_FieldCount(field_count), m_Fields(fields)
	{
	}
	~ClassTypeImp() {}

	virtual const char* Name();
	virtual int Category();
	virtual unsigned int Length();

	virtual unsigned int BaseCount();
	virtual InterfaceType* Bases(unsigned int bid);
	virtual unsigned int MethodCount();
	virtual MethodInfo* Methods(unsigned int mid);

	virtual unsigned int FieldCount();
	virtual FieldInfo* Fields(unsigned int fid);
};


/**
 * Inner types
 */
extern Type*      MTVoid;
extern Type*      MTBool;
extern Type*      MTSbyte;
extern Type*      MTByte;
extern Type*      MTShort;
extern Type*      MTWord;
extern Type*      MTLong;
extern Type*      MTDword;
extern Type*      MTHyper;
extern Type*      MTQword;
extern Type*      MTChar;
extern Type*      MTWchar;
extern Type*      MTFloat;
extern Type*      MTDouble;

extern ClassType* MTObject;

__END_NAMESPACE

#endif
